<h1><code ng:non-bindable=""></code>
    <span class="hint"></span>
</h1>
<div><a href="http://github.com/angular/angular.js/edit/master/docs/content/tutorial/step_05.ngdoc"
        class="improve-docs btn btn-primary">Improve this doc</a>

    <div class="tutorial-page tutorial-5-xhrs-dependency-injection-page">
        <ul doc-tutorial-nav="5"></ul>

        <p>Enough of building an app with three phones in a hard-coded dataset! Let's fetch a larger dataset
            from our server using one of angular's built-in <a href="api/ng">services</a> called <a href="api/ng.$http"><code>$http</code></a>.
            We will use angular's <a href="guide/di">dependency injection (DI)</a> to provide the service to the <code>PhoneListCtrl</code>
            controller.</p>

        <div doc-tutorial-reset="5">
        </div>

        <p>You should now see a list of 20 phones.</p>

        <p>The most important changes are listed below. You can see the full diff on <a
                href="https://github.com/angular/angular-phonecat/compare/step-4...step-5">GitHub</a>:</p>

        <h2 id="data">Data</h3>

            <p>The <code>app/phones/phones.json</code> file in your project is a dataset that contains a larger list of
                phones
                stored in the JSON format.</p>

            <p>Following is a sample of the file:
<pre class="prettyprint linenums">
[
 {
  "age": 13,
  "id": "motorola-defy-with-motoblur",
  "name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
  "snippet": "Are you ready for everything life throws your way?"
  ...
 },
...
]
</pre>

            <h2 id="controller">Controller</h3>

                <p>We'll use angular's <a href="api/ng.$http"><code>$http</code></a> service in our controller to make
                    an HTTP
                    request to your web server to fetch the data in the <code>app/phones/phones.json</code> file. <code>$http</code>
                    is just
                    one of several built-in <a href="guide/dev_guide.services">angular services</a> that handle common
                    operations
                    in web apps. Angular injects these services for you where you need them.</p>

                <p>Services are managed by angular's <a href="guide/di">DI subsystem</a>. Dependency injection
                    helps to make your web apps both well-structured (e.g., separate components for presentation, data,
                    and control) and loosely coupled (dependencies between components are not resolved by the
                    components themselves, but by the DI subsystem).</p>

                <p><strong><code>app/js/controllers.js:</code></strong>
<pre class="prettyprint linenums">
function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data;
  });

  $scope.orderProp = 'age';
}

//PhoneListCtrl.$inject = ['$scope', '$http'];
</pre>

                <p><code>$http</code> makes an HTTP GET request to our web server, asking for
                    <code>phone/phones.json</code> (the url is
                    relative to our <code>index.html</code> file). The server responds by providing the data in the json
                    file.
                    (The response might just as well have been dynamically generated by a backend server. To the
                    browser and our app they both look the same. For the sake of simplicity we used a json file in this
                    tutorial.)</p>

                <p>The <code>$http</code> service returns a <a href="api/ng.$q"><code>promise object</code></a> with a
                    <code>success</code>
                    method. We call this method to handle the asynchronous response and assign the phone data to the
                    scope controlled by this controller, as a model called <code>phones</code>. Notice that angular
                    detected the
                    json response and parsed it for us!</p>

                <p>To use a service in angular, you simply declare the names of the dependencies you need as arguments
                    to the controller's constructor function, as follows:</p>

<pre><code>function PhoneListCtrl($scope, $http) {...}
</code></pre>

                <p>Angular's dependency injector provides services to your controller when the controller is being
                    constructed. The dependency injector also takes care of creating any transitive dependencies the
                    service may have (services often depend upon other services).</p>

                <p>Note that the names of arguments are significant, because the injector uses these to look up the
                    dependencies.</p>

                <p><img class="diagram" src="img/tutorial/xhr_service_final.png"></p>

                <h3 id="dprefixnamingconvention">'$' Prefix Naming Convention</h4>

                    <p>You can create your own services, and in fact we will do exactly that in step 11. As a naming
                        convention, angular's built-in services, Scope methods and a few other angular APIs have a '$'
                        prefix in front of the name. Don't use a '$' prefix when naming your services and models, in
                        order
                        to avoid any possible naming collisions.</p>

                    <h3 id="anoteonminification">A Note on Minification</h4>

                        <p>Since angular infers the controller's dependencies from the names of arguments to the
                            controller's
                            constructor function, if you were to <a
                                    href="http://en.wikipedia.org/wiki/Minification_(programming)">minify</a> the
                            JavaScript code for <code>PhoneListCtrl</code> controller, all of its function arguments
                            would be
                            minified as well, and the dependency injector would not be able to identify services
                            correctly.</p>

                        <p>To overcome issues caused by minification, just assign an array with service identifier
                            strings
                            into the <code>$inject</code> property of the controller function, just like the last line
                            in the snippet
                            (commented out) suggests:</p>

<pre><code>PhoneListCtrl.$inject = ['$scope', '$http'];
</code></pre>

                        <p>There is also one more way to specify this dependency list and avoid minification issues —
                            using the
                            bracket notation which wraps the function to be injected into an array of strings
                            (representing the
                            dependency names) followed by the function to be injected:</p>

<pre><code>var PhoneListCtrl = ['$scope', '$http', function($scope, $http) { /* constructor body */ }];
</code></pre>

                        <p>Both of these methods work with any function that can be injected by Angular, so it's up to
                            your
                            project's style guide to decide which one you use.</p>

                        <h2 id="test">Test</h3>

                    <p><strong><code>test/unit/controllersSpec.js</code>:</strong></p>

                    <p>Because we started using dependency injection and our controller has dependencies, constructing
                        the
                        controller in our tests is a bit more complicated. We could use the <code>new</code> operator
                        and provide the
                        constructor with some kind of fake <code>$http</code> implementation. However, the recommended
                        (and easier) way
                        is to create a controller in the test environment in the same way that angular does it in the
                        production code behind the scenes, as follows:</p>

<pre class="prettyprint linenums">
describe('PhoneCat controllers', function() {

  describe('PhoneListCtrl', function(){
    var scope, ctrl, $httpBackend;

    // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
    // This allows us to inject a service but then attach it to a variable
    // with the same name as the service.
    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
      $httpBackend = _$httpBackend_;
      $httpBackend.expectGET('phones/phones.json').
          respond([{name: 'Nexus S'}, {name: 'Motorola DROID'}]);

      scope = $rootScope.$new();
      ctrl = $controller(PhoneListCtrl, {$scope: scope});
    }));
</pre>

                    <p>Note: Because we loaded Jasmine and <code>angular-mocks.js</code> in our test environment, we got
                        two helper
                        methods <a href="api/angular.mock.module"><code>module</code></a> and <a
                                href="api/angular.mock.inject"><code>inject</code></a> that we'll
                        use to access and configure the injector.</p>

                    <p>We created the controller in the test environment, as follows:</p>

                    <ul>
                        <li><p>We used the <code>inject</code> helper method to inject instances of
                            <a href="api/ng.$rootScope"><code>$rootScope</code></a>,
                            <a href="api/ng.$controller"><code>$controller</code></a> and
                            <a href="api/ng.$httpBackend"><code>$httpBackend</code></a> services into the Jasmine's
                            <code>beforeEach</code>
                            function. These instances come from an injector which is recreated from scratch for every
                            single
                            test. This guarantees that each test starts from a well known starting point and each test
                            is
                            isolated from the work done in other tests.</p></li>
                        <li><p>We created a new scope for our controller by calling <code>$rootScope.$new()</code></p>
                        </li>
                        <li><p>We called the injected <code>$controller</code> function passing the
                            <code>PhoneListCtrl</code> function and the created
                            scope as parameters.</p></li>
                    </ul>

                    <p>Because our code now uses the <code>$http</code> service to fetch the phone list data in our
                        controller, before
                        we create the <code>PhoneListCtrl</code> child scope, we need to tell the testing harness to
                        expect an
                        incoming request from the controller. To do this we:</p>

                    <ul>
                        <li><p>Request <code>$httpBackend</code> service to be injected into our <code>beforeEach</code>
                            function. This is a mock
                            version of the service that in a production environment facilitates all XHR and JSONP
                            requests.
                            The mock version of this service allows you to write tests without having to deal with
                            native APIs and the global state associated with them — both of which make testing a
                            nightmare.</p></li>
                        <li><p>Use the <code>$httpBackend.expectGET</code> method to train the <code>$httpBackend</code>
                            service to expect an incoming
                            HTTP request and tell it what to respond with. Note that the responses are not returned
                            until we call
                            the <code>$httpBackend.flush</code> method.</p></li>
                    </ul>

                    <p>Now, we will make assertions to verify that the <code>phones</code> model doesn't exist on <code>scope</code>
                        before
                        the response is received:</p>

<pre class="prettyprint linenums">
    it('should create "phones" model with 2 phones fetched from xhr', function() {
      expect(scope.phones).toBeUndefined();
      $httpBackend.flush();

      expect(scope.phones).toEqual([{name: 'Nexus S'},
                                   {name: 'Motorola DROID'}]);
    });
</pre>

                    <ul>
                        <li><p>We flush the request queue in the browser by calling <code>$httpBackend.flush()</code>.
                            This causes the
                            promise returned by the <code>$http</code> service to be resolved with the trained response.
                        </p></li>
                        <li><p>We make the assertions, verifying that the phone model now exists on the scope.</p></li>
                    </ul>

                    <p>Finally, we verify that the default value of <code>orderProp</code> is set correctly:</p>

<pre class="prettyprint linenums">
    it('should set the default value of orderProp model', function() {
      expect(scope.orderProp).toBe('age');
    });
</pre>

                    <p>You should now see the following output in the Karma tab:</p>

<pre><code> Chrome 22.0: Executed 2 of 2 SUCCESS (0.028 secs / 0.007 secs)
</code></pre>

                    <h1 id="experiments">Experiments
            </h2>

            <ul>
                <li><p>At the bottom of <code>index.html</code>, add a <code>{{phones | json}}</code> binding to see the
                    list of phones
                    displayed in json format.</p></li>
                <li><p>In the <code>PhoneListCtrl</code> controller, pre-process the http response by limiting the
                    number of phones
                    to the first 5 in the list. Use the following code in the $http callback:</p>

<pre><code> $scope.phones = data.splice(0, 5);
</code></pre>
                </li>
            </ul>

            <h1 id="summary">Summary</h2>

        <p>Now that you have learned how easy it is to use angular services (thanks to Angular's dependency
            injection), go to <a href="tutorial/step_06">step 6</a>, where you will add some
            thumbnail images of phones and some links.</p>

        <ul doc-tutorial-nav="5"></ul>
    </div>
</div>
